/*
 * SelectionPanel.java
 *
 * Created on 3. Juni 2003, 17:18
 */

package de.axelwernicke.mypod.gui;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;

import javax.swing.DefaultListModel;


/** This panel provides a standard way to manage selection in lists
 *
 * @author  axelwe
 */
public class SelectionPanel extends javax.swing.JPanel {
    /** Creates new form SelectionPanel */
    public SelectionPanel() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() { //GEN-BEGIN:initComponents
    
        java.awt.GridBagConstraints gridBagConstraints;

        selectedScrollPane = new javax.swing.JScrollPane();
        selectedList = new javax.swing.JList();
        unselectedScrollPane = new javax.swing.JScrollPane();
        unselectedList = new javax.swing.JList();
        buttonPanel = new javax.swing.JPanel();
        dummyPanel = new javax.swing.JPanel();
        selectAllButton = new javax.swing.JButton();
        selectButton = new javax.swing.JButton();
        unselectButton = new javax.swing.JButton();
        unselectAllButton = new javax.swing.JButton();
        dummyPanel1 = new javax.swing.JPanel();

        setLayout(new java.awt.GridBagLayout());

        selectedScrollPane.setPreferredSize(new java.awt.Dimension(50, 3));
        selectedList.setFont(new java.awt.Font("Dialog", 0, 10));
        selectedList.setModel(new DefaultListModel());
        selectedList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                selectedListValueChanged(evt);
            }
        });
        selectedList.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                selectedListMouseClicked(evt);
            }
        });

        selectedScrollPane.setViewportView(selectedList);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.weighty = 0.1;
        add(selectedScrollPane, gridBagConstraints);

        unselectedScrollPane.setPreferredSize(new java.awt.Dimension(50, 3));
        unselectedList.setFont(new java.awt.Font("Dialog", 0, 10));
        unselectedList.setModel(new DefaultListModel());
        unselectedList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                unselectedListValueChanged(evt);
            }
        });
        unselectedList.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                unselectedListMouseClicked(evt);
            }
        });

        unselectedScrollPane.setViewportView(unselectedList);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.weighty = 0.1;
        add(unselectedScrollPane, gridBagConstraints);

        buttonPanel.setLayout(new java.awt.GridBagLayout());

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridy = 0;
        buttonPanel.add(dummyPanel, gridBagConstraints);

        selectAllButton.setText(GuiUtils.getStringLocalized("all"));
        selectAllButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                selectAllButtonActionPerformed(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(12, 11, 0, 11);
        buttonPanel.add(selectAllButton, gridBagConstraints);

        selectButton.setText("<");
        selectButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                selectButtonActionPerformed(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(5, 11, 0, 11);
        buttonPanel.add(selectButton, gridBagConstraints);

        unselectButton.setText(">");
        unselectButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                unselectButtonActionPerformed(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(5, 11, 0, 11);
        buttonPanel.add(unselectButton, gridBagConstraints);

        unselectAllButton.setText(GuiUtils.getStringLocalized("none"));
        unselectAllButton.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    unselectAllButtonActionPerformed(evt);
                }
            });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridy = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(5, 11, 12, 11);
        buttonPanel.add(unselectAllButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridy = 5;
        buttonPanel.add(dummyPanel1, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
        add(buttonPanel, gridBagConstraints);
    } //GEN-END:initComponents

    /** Handles value changed events for the selected list.
     *        Most important it makes sure that selected values are displayed. The list is scrolled if neccessary.
     */
    private void selectedListValueChanged(javax.swing.event.ListSelectionEvent evt) //GEN-FIRST:event_selectedListValueChanged
     { //GEN-HEADEREND:event_selectedListValueChanged
        int index = this.selectedList.getSelectedIndex();

        // check if the index is valid and its no intermediate event
        if ((index >= 0) && !evt.getValueIsAdjusting()) {
            // make sure the selection is visible
            this.selectedList.scrollRectToVisible(this.selectedList.getCellBounds(index, index));
        }
    } //GEN-LAST:event_selectedListValueChanged

    /** Handles value changed events for the selected list.
     *        Most important it makes sure that selected values are displayed. The list is scrolled if neccessary.
     */
    private void unselectedListValueChanged(javax.swing.event.ListSelectionEvent evt) //GEN-FIRST:event_unselectedListValueChanged
     { //GEN-HEADEREND:event_unselectedListValueChanged
        int index = this.unselectedList.getSelectedIndex();

        // check if the index is valid and its no intermediate event
        if ((index >= 0) && !evt.getValueIsAdjusting()) {
            // make sure the selection is visible
            this.unselectedList.scrollRectToVisible(this.unselectedList.getCellBounds(index, index));
        }
    } //GEN-LAST:event_unselectedListValueChanged

    /** Handles the click within the selected list
     * @param evt to handle
     */
    private void selectedListMouseClicked(java.awt.event.MouseEvent evt) //GEN-FIRST:event_selectedListMouseClicked
     { //GEN-HEADEREND:event_selectedListMouseClicked
        if (evt.getClickCount() == 2) {
            unselectButtonActionPerformed(null);
        }
    } //GEN-LAST:event_selectedListMouseClicked

    /** Handles the click within the unselected list
     * @param evt to handle
     */
    private void unselectedListMouseClicked(java.awt.event.MouseEvent evt) //GEN-FIRST:event_unselectedListMouseClicked
     { //GEN-HEADEREND:event_unselectedListMouseClicked
        if (evt.getClickCount() == 2) {
            selectButtonActionPerformed(null);
        }
    } //GEN-LAST:event_unselectedListMouseClicked

    /** Handles the click on the unselect all button
     * @param evt to handle
     */
    private void unselectAllButtonActionPerformed(java.awt.event.ActionEvent evt) //GEN-FIRST:event_unselectAllButtonActionPerformed
     { //GEN-HEADEREND:event_unselectAllButtonActionPerformed
        // move all elements
        moveAll(this.getSelectedListModel(), this.getUnselectedListModel());

        // sort unselected list
        sort(this.getUnselectedListModel());
    } //GEN-LAST:event_unselectAllButtonActionPerformed

    /** Handles the click on the unselect button
     * @param evt to handle
     */
    private void unselectButtonActionPerformed(java.awt.event.ActionEvent evt) //GEN-FIRST:event_unselectButtonActionPerformed
     { //GEN-HEADEREND:event_unselectButtonActionPerformed
        // get all selected items in the selected playlist
        Object[] objects = this.selectedList.getSelectedValues();

        // move them
        move(this.getSelectedListModel(), this.getUnselectedListModel(), objects);

        // sort unselected list
        sort(this.getUnselectedListModel());
    } //GEN-LAST:event_unselectButtonActionPerformed

    /** Handles the click on the select button
     * @param evt to handle
     */
    private void selectButtonActionPerformed(java.awt.event.ActionEvent evt) //GEN-FIRST:event_selectButtonActionPerformed
     { //GEN-HEADEREND:event_selectButtonActionPerformed
        // get all selected items in the selected playlist
        Object[] objects = this.unselectedList.getSelectedValues();

        // move all elements
        move(this.getUnselectedListModel(), this.getSelectedListModel(), objects);

        // sort selected list
        sort(this.getSelectedListModel());
    } //GEN-LAST:event_selectButtonActionPerformed

    /** Handles the click on the select all button
     * @param evt to handle
     */
    private void selectAllButtonActionPerformed(java.awt.event.ActionEvent evt) //GEN-FIRST:event_selectAllButtonActionPerformed
     { //GEN-HEADEREND:event_selectAllButtonActionPerformed
        // move them all
        moveAll(this.getUnselectedListModel(), this.getSelectedListModel());

        // sort selected list
        sort(this.getSelectedListModel());
    } //GEN-LAST:event_selectAllButtonActionPerformed

    /** Sets list model for list of unselected items
     */
    void setUnselectedListModel(DefaultListModel model) {
        this.unselectedList.setModel(model);
    }

    /** Sets list model for list of unselected items
     */
    DefaultListModel getUnselectedListModel() {
        return (DefaultListModel) this.unselectedList.getModel();
    }

    /** Sets list model for list of unselected items
     * @param model
     */
    void setSelectedListModel(DefaultListModel model) {
        this.selectedList.setModel(model);
    }

    /** Sets list model for list of unselected items
     */
    DefaultListModel getSelectedListModel() {
        return (DefaultListModel) this.selectedList.getModel();
    }

    /**
     * Gets the content of the selected list
     */
    public List<String> getSelection() {
        DefaultListModel selectedListModel = this.getSelectedListModel();
        List<String> result = new ArrayList<String>(selectedListModel.size());

        for (Enumeration<?> enumeration = selectedListModel.elements();
             enumeration.hasMoreElements();) {
            result.add((String) enumeration.nextElement());
        }

        return result;
    }

    /**
     * Adds some objects to the selection list and removes them from the unselected list if they are in there
     * @param selection
     */
    void select(Collection<?> selection) {
        move(this.getUnselectedListModel(), this.getSelectedListModel(), selection.toArray());
    }

//	/** Adds an objects to the selection list and removes it from the unselected list if it is in there
//	 * @param selection object to select
//	 */
//	void select(Object selection) {
//		move( this.getUnselectedListModel(), this.getSelectedListModel(), selection );
//	}

    /**
     * Set enabling for most important components
     * @param value to set
     */
    public void setEnabled(boolean value) {
        this.selectedList.setEnabled(value);
        this.unselectedList.setEnabled(value);
        this.selectAllButton.setEnabled(value);
        this.selectButton.setEnabled(value);
        this.unselectAllButton.setEnabled(value);
        this.unselectButton.setEnabled(value);
    }

    /**
     * Moves all object from one list model to another
     * @param src list model - all its content is moved
     * @param dest list model
     */
    private void moveAll(DefaultListModel src, DefaultListModel dest) {
        move(src, dest, src.toArray());
    }

    /**
     * Moves objects from one list model to another
     * @param src list model
     * @param dest list model
     * @param obj array of objects to move from src to dest
     */
    private void move(DefaultListModel src, DefaultListModel dest, Object[] obj) {
        int length = obj.length;
        for (int i = 0; i < length; i++) {
            move(src, dest, obj[i]);
        }
    }

    /**
     * Moves an object from one list model to another
     * @param src list model
     * @param dest list model
     * @param obj object to move from src to dest
     */
    private void move(DefaultListModel src, DefaultListModel dest, Object obj) {
        dest.addElement(obj);
        if (src.contains(obj)) {
            src.removeElement(obj);
        }
    }

    /**
     * Sorts a list model
     * @param listModel to sort
     */
    private void sort(DefaultListModel listModel) {
        // list model -> array
        Object[] objects = listModel.toArray();

        // sort - sometimes this throws an exception :( - greetings to SUN - I always thought they were perfect :)
        try {
            Arrays.sort(objects, Collator.getInstance());
        } catch (Exception e) {
            e.printStackTrace();
        }

        // array -> list model
        listModel.clear();
        for (int i = 0; i < objects.length; i++) {
            listModel.addElement(objects[i]);
        }
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel buttonPanel;
    private javax.swing.JPanel dummyPanel;
    private javax.swing.JPanel dummyPanel1;
    private javax.swing.JButton selectAllButton;
    private javax.swing.JButton selectButton;
    private javax.swing.JList selectedList;
    private javax.swing.JScrollPane selectedScrollPane;
    private javax.swing.JButton unselectAllButton;
    private javax.swing.JButton unselectButton;
    private javax.swing.JList unselectedList;
    private javax.swing.JScrollPane unselectedScrollPane;

    // End of variables declaration//GEN-END:variables
}
